from functools import wraps
from flask import request
from flask_jwt_extended import JWTManager, create_access_token, create_refresh_token, get_current_user, \
    verify_jwt_in_request

__all__ = ["login_required", "admin_required", "group_required", "tokens"]

from app.serve.user.user import UserServe
from app.util.exception import WtreesReturn, ErrorType

SCOPE = "lin"
jwt = JWTManager()
identity = dict(uid=0, scope=SCOPE)


def admin_required(fn):
    @wraps(fn)
    def wrapper(*args, **kwargs):
        verify_jwt_in_request()
        current_user = get_current_user()
        if not current_user.is_admin:
            print(1)
            # raise UnAuthentication("只有超级管理员可操作")
        return fn(*args, **kwargs)

    return wrapper


def group_required(fn):
    @wraps(fn)
    def wrapper(*args, **kwargs):
        verify_jwt_in_request()
        current_user = get_current_user()
        # check current user is active or not
        # 判断当前用户是否为激活状态
        _check_is_active(current_user)
        # not admin
        if not current_user.is_admin:
            from . import find_group_ids_by_user_id

            group_ids = find_group_ids_by_user_id(current_user.id)
            if group_ids is None:
                print(1)
                # raise UnAuthentication("您还不属于任何分组，请联系超级管理员获得权限")
            from . import is_user_allowed

            if not is_user_allowed(group_ids):
                print(1)
                # raise UnAuthentication("权限不够，请联系超级管理员获得权限")
            else:
                return fn(*args, **kwargs)
        else:
            return fn(*args, **kwargs)

    return wrapper


def login_required(fn):
    @wraps(fn)
    def wrapper(*args, **kwargs):
        verify_jwt_in_request()
        _check_is_active(current_user=get_current_user())
        return fn(*args, **kwargs)

    return wrapper


@jwt.user_loader_callback_loader
def user_loader_callback(identity):
    if identity["scope"] != SCOPE:
        raise print(1)
    if "remote_addr" in identity.keys() and identity["remote_addr"] != request.remote_addr:
        return WtreesReturn.data(ErrorType.SESSION_ID_IS_EXPIRED)

    user = UserServe.query.filter_by(id=identity["uid"]).first()
    if user is None:
        print(1)
    return user


@jwt.expired_token_loader
def expired_loader_callback():
    return WtreesReturn.data(ErrorType.SESSION_ID_IS_EXPIRED)


@jwt.invalid_token_loader
def invalid_loader_callback(e):
    return print(1)


@jwt.unauthorized_loader
def unauthorized_loader_callback(e):
    return WtreesReturn.data(ErrorType.SESSION_ID_IS_EXPIRED)


@jwt.user_claims_loader
def add_claims_to_access_token(identity):
    return {
        "uid": identity["uid"],
        "scope": identity["scope"],
        "remote_addr": identity["remote_addr"]
        if "remote_addr" in identity.keys()
        else None,
    }


def verify_access_token():
    __verify_token("access")


def verify_refresh_token():
    __verify_token("refresh")


def __verify_token(request_type):
    from flask import request
    from flask_jwt_extended.config import config
    from flask_jwt_extended.utils import verify_token_claims
    from flask_jwt_extended.view_decorators import _decode_jwt_from_cookies as decode

    try:
        from flask import _app_ctx_stack as ctx_stack
    except ImportError:
        from flask import _request_ctx_stack as ctx_stack

    if request.method not in config.exempt_methods:
        jwt_data = decode(request_type=request_type)
        ctx_stack.top.jwt = jwt_data
        verify_token_claims(jwt_data)


def _check_is_active(current_user):
    if not current_user.is_active:
        print(1)


def tokens(user, verify_remote_addr=False):
    identity["uid"] = user.id
    if verify_remote_addr:
        identity["remote_addr"] = request.remote_addr
    access_token = create_access_token(identity=identity)
    refresh_token = create_refresh_token(identity=identity)
    return access_token, refresh_token
